home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 30
/
Aminet 30 (1999)(Schatztruhe)[!][Apr 1999].iso
/
Aminet
/
util
/
conv
/
makedoc-palm.lha
/
makedoc8.cc
< prev
Wrap
C/C++ Source or Header
|
1998-09-20
|
33KB
|
1,147 lines
// MakeDoc
// version 0.8
//
// Compresses text files into a format that is ready to export to a Pilot
// and work with Rick Bram's PilotDOC reader.
//
// Freeware
//
// ver 0.6 enforce 31 char limit on database names
// ver 0.7 change header and record0 to structs
// ver 0.7a minor mispellings and portability issues
/**********************************************************************
* Rick,
*
* I made some more changes to fix another portability problem. It seems
* that SOME compilers will pad a structure to a DWORD boundary when you
* use the sizeof operator. In particular, for the Solaris compiler, the
* 78 byte tDocHeader structure is reported as having 80 bytes. This shifts
* EVERYTHING by two bytes and wreaks havoc in the generated .prc file.
* I fixed this (look at the comments in struct tDocHeader and the DOCHEADSZ
* definition) in the two places it occurred.
*
* I also fixed a spelling error in an error message.
*
* I also changed the usage message to say this is version 0.7a (rather than
* 0.6).
*
* I also changed the return type of main() to be int and added various
* calls to exit() as needed. Needed for portability and correctness.
*
* -- Harold Bamford
**********************************************************************/
//
// Modifications by Kadar Tanuwidjaja (ktan8@dgs.monash.edu.au)
// ver 0.8 add -q for quiet mode
// add -p for private flag
// add -c for category
// add -i for info (title, private flag, category)
// add -m for changing title, category or private flag
// default for out-filename is in-filename.pdb (encoding mode)
// default for title is in-filename (encoding mode)
// default for out-filename is stdout (decoding mode)
// modify command syntax, but still maintain backward
// compatibiliy (see makedoc -h for more details)
#define UNIX 1
#ifdef sparc
# ifndef UNIX
# define UNIX 1
# endif
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//template<class A> A max(const A& a, const A& b) {return (a<b) ? b : a;}
#define max(a,b) ((a>b) ? a : b)
typedef unsigned char byte;
typedef unsigned long DWORD;
typedef unsigned short WORD;
#define DISP_BITS 11
#define COUNT_BITS 3
// all numbers in these structs are big-endian, MAC format
struct tDocHeader {
char sName[32]; // 32 bytes
DWORD dwUnknown1; // 36 2b file attribute & 2b version
DWORD dwTime1; // 40 Creation Date
DWORD dwTime2; // 44 Modification Date
DWORD dwTime3; // 48 Last Backup Date
DWORD dwLastSync; // 52 Modication Number
DWORD ofsSort; // 56 AppInfo Area
DWORD ofsCatagories; // 60 SortInfo Area
DWORD dwCreator; // 64 Database Type
DWORD dwType; // 68 Creator ID
DWORD dwUnknown2; // 72 Unique ID seed
DWORD dwUnknown3; // 76 Next Record List ID
WORD wNumRecs; // 78 Number of Records
};
// Some compilers pad structures out to DWORD boundaries so using sizeof()
// doesn't give the intended result.
#define DOCHEADSZ 78
struct tDocRecord0 {
WORD wVersion; // 1=plain text, 2=compressed
WORD wSpare;
DWORD dwStoryLen; // in bytes, when decompressed
WORD wNumRecs; // text records only; equals tDocHeader.wNumRec
s-1
WORD wRecSize; // usually 0x1000
DWORD dwSpare2;
};
////////////// utilities //////////////////////////////////////
WORD SwapWord21(WORD r)
{
return (r>>8) + (r<<8);
}
WORD SwapWord12(WORD r)
{
return r;
}
DWORD SwapLong4321(DWORD r)
{
return ((r>>24) & 0xFF) + (r<<24) + ((r>>8) & 0xFF00) + ((r<<8) & 0xFF
0000);
}
DWORD SwapLong1234(DWORD r)
{
return r;
}
WORD (*SwapWord)(WORD r) = NULL;
DWORD (*SwapLong)(DWORD r) = NULL;
// copy bytes into a word and double word and see how they fall,
// then choose the appropriate swappers to make things come out
// in the right order.
int SwapChoose()
{
union { char b[2]; WORD w; } w;
union { char b[4]; DWORD d; } d;
strncpy(w.b, "\1\2", 2);
strncpy(d.b, "\1\2\3\4", 4);
if (w.w == 0x0201)
SwapWord = SwapWord21;
else if (w.w == 0x0102)
SwapWord = SwapWord12;
else
return 0;
if (d.d == 0x04030201)
SwapLong = SwapLong4321;
else if (d.d == 0x01020304)
SwapLong = SwapLong1234;
else
return 0;
return 1;
}
// replacement for strstr() which deals with 0's in the data
byte* memfind(byte* t, int t_len, byte* m, int m_len)
{
int i;
for (i = t_len - m_len + 1 ; i>0; i--, t++)
if (t[0]==m[0] && memcmp(t,m,m_len)==0)
return t;
return 0;
}
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
///////////////////// //////////////////////
///////////////////// tBuf class //////////////////////
///////////////////// //////////////////////
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
struct tBuf {
byte* buf;
unsigned len;
tBuf() {buf = new byte[len = 6000];};
~tBuf() { if (buf) delete[] buf; }
unsigned Len() const { return len; }
unsigned RemoveBinary();
unsigned Decompress();
unsigned Compress();
unsigned Issue(byte src, int& bSpace);
unsigned DuplicateCR();
void Clear() {delete[] buf; buf = new byte[len = 6000]; }
void Dump() {printf("\nbuffer len=%d",len);}
};
//
// Issue()
//
// action: handle the details of writing a single
// character to the compressed stream
//
unsigned
tBuf::Issue(byte src, int& bSpace)
{
int iDest = len;
byte* dest = buf;
// if there is an outstanding space char, see if
// we can squeeze it in with an ASCII char
if (bSpace)
{
if (src>=0x40 && src<=0x7F)
dest[iDest++] = src ^ 0x80;
else
{
// couldn't squeeze it in, so issue the space char by i
tself
// most chars go out simple, except the range 1...8,0x8
0...0xFF
dest[iDest++] = ' ';
if (src<0x80 && (src==0 || src>8) )
dest[iDest++] = src;
else
dest[iDest++] = 1, dest[iDest++] = src;
}
// knock down the space flag
bSpace = 0;
}
else
{
// check for a space char
if (src==' ')
bSpace = 1;
else
{
if (src<0x80 && (src==0 || src>8))
dest[iDest++] = src;
else
dest[iDest++] = 1, dest[iDest++] = src;
}
}
len = iDest;
return iDest;
}
//
// Compress
//
// params: none
//
// action: takes the given buffer,
// and compresses
// the original data down into a second bu
ffer
//
// comment: This version make heavy use of walking pointers.
//
unsigned tBuf::Compress()
{
int i,j;
int bSpace = 0;
// run through the input buffer
byte* pBuffer; // points to the input buffer
byte* pHit; // points to a walking test hit; works upwards
on successive matches
byte* pPrevHit; // previous value of pHit
byte* pTestHead; // current test string
byte* pTestTail; // current walking pointer; one past the curren
t test buffer
byte* pEnd; // 1 past the end of the input buffer
pHit = pPrevHit = pTestHead = pBuffer = buf;
pTestTail = pTestHead+1;
pEnd = buf + len;
//printf("pointers %x %x",pTestTail, pEnd);
//printf("\nstart compression buf len=%d",len);
// make a dest buffer and reassign the local buffer
buf = new byte[6000];
len = 0; // used to walk through the output buffer
// loop, absorbing one more char from the input buffer on each pass
for (; pTestHead != pEnd; pTestTail++)
{
//printf("\npointers pTestHead %x pTestTail %x pTestHead[]=%x %x",pTestHead, pT
estTail, pTestHead[0], pTestHead[1]);
// establish where the scan can begin
if (pTestHead - pPrevHit > ((1<<DISP_BITS)-1))
pPrevHit = pTestHead - ((1<<DISP_BITS)-1);
// scan in the previous data for a match
pHit = memfind(pPrevHit, pTestTail - pPrevHit, pTestHead, pTest
Tail - pTestHead);
if (pHit==0)
printf("!! bug source %x%x%x, dest %x%x%x, %d bytes",
pPrevHit[0],
pPrevHit[1],pPrevHit[2],pTestHead[0],
pTestHead[1], pTestHead[2], pTestTail-pTestHead);
// on a mismatch or end of buffer, issued codes
if (pHit==0
|| pHit==pTestHead
|| pTestTail-pTestHead>(1<<COUNT_BITS)+2
|| pTestTail==pEnd)
{
// issued the codes
// first, check for short runs
if (pTestTail-pTestHead < 4)
{
//printf("\nissue a char %x",pTestHead[0]);
Issue(pTestHead[0], bSpace);
pTestHead++;
}
// for longer runs, issue a run-code
else
{
// issue space char if required
if (bSpace) buf[len++] = ' ', bSpace = 0;
unsigned int dist = pTestHead - pPrevHit;
unsigned int compound = (dist << COUNT_BITS) +
pTestTail-pTestHead - 4;
if (dist>=(1<<DISP_BITS)) printf("\n!! error dist overflow");
if (pTestTail-pTestHead-4>7) printf("\n!! error dist overflow");
buf[len++] = 0x80 + (compound>>8);
buf[len++] = compound & 0xFF;
//printf("\nissuing code for sequence len %d <%c%c%c>",pTestTail-pTestHead-1,pT
estHead[0],pTestHead[1],pTestHead[2]);
//printf("\n <%x%x>",pOut[-2],pOut[-1]);
// and start again
pTestHead = pTestTail-1;
}
// start the search again
pPrevHit = pBuffer;
}
// got a match
else
{
pPrevHit = pHit;
}
//printf("pointers %x %x %x",pTestHead, pTestTail, pPrevHit);
// when we get to the end of the buffer, don't inc past the end
// this forces the residue chars out one at a time
if (pTestTail==pEnd) pTestTail--;
}
// clean up any dangling spaces
if (bSpace) buf[len++] = ' ';
// final scan to merge consecutive high chars together
int k;
for (i=k=0; i<len; i++,k++)
{
buf[k] = buf[i];
// skip the run-length codes
if (buf[k]>=0x80 && buf[k]<0xC0)
buf[++k] = buf[++i];
// if we hit a high char marker, look ahead for another
else if (buf[k]==1)
{
buf[k+1] = buf[i+1];
while (i+2<len && buf[i+2]==1 && buf[k]<8)
{
buf[k]++;
buf[k+buf[k]] = buf[i+3];
i+=2;
}
k += buf[k]; i++;
}
}
// delete original buffer
delete[] pBuffer;
len = k;
return k;
}
/*
Decompress
params: none
action: make a new buffer
run through the source data
check the 4 cases:
0,9...7F represent self
1...8 escape n chars
80...bf reference earlier run
c0...ff space+ASCII
*/
unsigned
tBuf::Decompress()
{
// we "know" that all decompresses fit within 4096, right?
byte* pOut = new byte[6000];
byte* in_buf = buf;
byte* out_buf = pOut;
int i,j;
for (j=i=0; j<len; )
{
unsigned int c;
// take a char from the input buffer
c = in_buf[j++];
// separate the char into zones: 0, 1...8, 9...0x7F, 0x80...0xB
F, 0xC0...0xFF
// codes 1...8 mean copy that many bytes; for accented chars &
binary
if (c>0 && c<9)
while(c--) out_buf[i++] = in_buf[j++];
// codes 0, 9...0x7F represent themselves
else if (c<0x80)
out_buf[i++] = c;
// codes 0xC0...0xFF represent "space + ascii char"
else if (c>=0xC0)
out_buf[i++] = ' ', out_buf[i++] = c ^ 0x80;
// codes 0x80...0xBf represent sequences
else
{
int m,n;
c <<= 8;
c += in_buf[j++];
m = (c & 0x3FFF) >> COUNT_BITS;
n = c & ((1<<COUNT_BITS) - 1);
n += 3;
while (n--)
{
out_buf[i] = out_buf[i-m];
i++;
}
}
}
delete[] buf;
buf = pOut;
len = i;
return i;
}
unsigned tBuf::DuplicateCR()
{
byte* pBuf = new byte[2*len];
int k,j;
for (j=k=0; j<len; j++, k++)
{
pBuf[k] = buf[j];
if (pBuf[k]==0x0A) pBuf[k++] = 0x0D, pBuf[k] = 0x0A;
}
delete[] buf;
buf = pBuf;
len = k;
return k;
}
// this nasty little beast removes really low ASCII and 0's
// and handles the CR problem
//
// if a cr appears before a lf, then remove the cr
// if a cr appears in isolation, change to a lf
unsigned tBuf::RemoveBinary()
{
byte* in_buf = buf;
byte* out_buf = new byte[len];
int k,j;
for (j=k=0; j<len; j++,k++)
{
// copy each byte
out_buf[k] = in_buf[j];
// throw away really low ASCII
if ((out_buf[k]>=0 && out_buf[k]<9)) k--;
// for CR
if (out_buf[k]==0x0D)
{
// if next is LF, then drop it
if (j<len-1 && in_buf[j+1]==0x0A)
k--;
else // turn it into a LF
out_buf[k] = 0x0A;
}
}
delete[] buf;
buf = out_buf;
len = k;
return k;
}
void out_word(short w, FILE* fout)
{
short m = SwapWord(w);
fwrite(&m,2,1,fout);
}
void out_long(long d, FILE* fout)
{
long d1 = SwapLong(d);
fwrite(&d1,4,1,fout);
}
//////////////////////////////////////////////////
// Info Mode
//////////////////////////////////////////////////
void Info(char* src)
{
FILE* fin;
FILE* fout;
fin = fopen(src,"rb");
if (fin==0)
{
printf("problem opening source file %s", src);
#if UNIX
printf("\n");
#endif
exit(2);
}
// just holds the first few bytes of the file
byte buf[0x100];
tDocHeader head;
fread(&head, 1, DOCHEADSZ, fin);
if (strncmp((char *)&head.dwType, "REAd", 4) != 0
|| strncmp((char *)&head.dwCreator, "TEXt", 4) != 0)
{
//printf("file contains %.4s, %.4s", (char *)&head.dwCreator, (char *
)&head.dwType);
printf("%s is not a DOC file", src);
#if UNIX
printf("\n");
#endif
exit(3);
}
WORD wPos;
int bPrivate = 0;
int bCategory = 0;
// point to start of index
fseek(fin, 0x4E + 4, SEEK_SET);
// read the location of the first record
fread(&wPos, 1, 1, fin);
bPrivate = (int) (wPos & 0x10) / 16;
bCategory = (int) wPos & 0x0F;
printf("%s p%d c%02d",head.sName, bPrivate, bCategory);
fclose(fin);
}
//////////////////////////////////////////////////
// Modify Mode
//////////////////////////////////////////////////
void Modify(char* src, char* title, int bQuiet, int bPrivate, int bCategory )
{
FILE* fin;
fin = fopen(src,"r+b");
if (fin==0)
{
printf("problem opening source file %s", src);
#if UNIX
printf("\n");
#endif
exit(2);
}
// just holds the first few bytes of the file
byte buf[0x100];
tDocHeader head;
fread(&head, 1, DOCHEADSZ, fin);
if (strncmp((char *)&head.dwType, "REAd", 4) != 0
|| strncmp((char *)&head.dwCreator, "TEXt", 4) != 0)
{
//printf("file contains %.4s, %.4s", (char *)&head.dwCreator, (char *
)&head.dwType);
printf("%s is not a DOC file", src);
#if UNIX
printf("\n");
#endif
exit(3);
}
if(!bQuiet) printf("Modifying %s",src);
if ( title[0] != '\0' )
{
if ( strcmp(head.sName, title) == 0)
{
if(!bQuiet) printf("\n current title is similar");
}
else
{
if(!bQuiet) printf("\n changing title from %s to %s", head.sName,
title);
sprintf(head.sName,"%.31s",title);
head.sName[31] = 0;
}
}
fseek(fin, 0, SEEK_SET);
fwrite(&head,1,DOCHEADSZ,fin);
WORD wNumRecs = SwapWord(head.wNumRecs); // the number of records to
follow
WORD wPos;
int bPrivateCurr;
int bCategoryCurr;
int bChange = 0;
// point to start of index
fseek(fin, 0x4E + 4, SEEK_SET);
// read the location of the first record
fread(&wPos, 1, 1, fin);
bPrivateCurr = (int) (wPos & 0x10) / 16;
bCategoryCurr = (int) wPos & 0x0F;
if ( bPrivate < 2 )
{
if ( bPrivate == bPrivateCurr)
{
if(!bQuiet) printf("\n current private flag is similar");
}
else
{
if(!bQuiet) printf("\n changing private flag from %d to %d", bPriv
ateCurr, bPrivate);
bChange = 1;
wPos = wPos & 0xEF; // turn off the 5th bit
wPos = wPos | (bPrivate * 16);
}
}
if ( bCategory < 16 )
{
if ( bCategory == bCategoryCurr)
{
if(!bQuiet) printf("\n current category is similar");
}
else
{
if(!bQuiet) printf("\n changing category from %d to %d", bCategory
Curr, bCategory);
bChange = 1;
wPos = wPos & 0xF0; // turn off the 1th to 4th bits
wPos = wPos | bCategory;
}
}
if(bChange) for ( int i = 0; i < wNumRecs; i++)
{
fseek(fin, 0x4E + 4 + i*8, SEEK_SET);
fwrite(&wPos, 1, 1, fin);
}
fclose(fin);
}
//////////////////////////////////////////////////
// Decode Mode
//////////////////////////////////////////////////
void Decode(char* src, char* dest, int bQuiet, int bBinary)
{
if ( dest[0] == '\0' )
{
strcpy(dest, "/dev/stdout");
bQuiet = 1;
}
FILE* fin;
FILE* fout;
fin = fopen(src,"rb");
if (fin==0)
{
printf("problem opening source file %s", src);
#if UNIX
printf("\n");
#endif
exit(2);
}
// just holds the first few bytes of the file
byte buf[0x100];
tDocHeader head;
fread(&head, 1, DOCHEADSZ, fin);
if (strncmp((char *)&head.dwType, "REAd", 4) != 0
|| strncmp((char *)&head.dwCreator, "TEXt", 4) != 0)
{
//printf("file contains %.4s, %.4s", (char *)&head.dwCreator, (char *
)&head.dwType);
printf("%s is not a DOC file", src);
#if UNIX
printf("\n");
#endif
exit(3);
}
WORD bCompressed;
DWORD dwPos;
tDocRecord0 rec0;
// point to start of index
fseek(fin, 0x4E, SEEK_SET);
// read the location of the first record
fread(&dwPos, 4, 1, fin);
dwPos = SwapLong(dwPos);
fseek(fin, dwPos, SEEK_SET);
fread(&rec0, sizeof(rec0), 1, fin);
bCompressed = SwapWord(rec0.wVersion);
if (bCompressed!=1 && bCompressed!=2)
printf("WARNING: unknown file compression type: %d", bCompresse
d);
bCompressed--;
fout = fopen(dest,"wb");
if (fout==0)
{
printf("problem opening output file %s",dest);
#if UNIX
printf("\n");
#endif
exit(2);
}
DWORD dwLen;
fseek(fin,0,SEEK_END);
dwLen = ftell(fin);
WORD nRecs;
nRecs = SwapWord(head.wNumRecs) - 1;
// this is the main record buffer
// it knows how to stretch to accomodate the decompress
tBuf t;
DWORD dwRecLen;
for (int i=0; i<nRecs; i++)
{
// read the record offset
fseek(fin, 0x56 + 8*i, SEEK_SET);
fread(&dwPos, 4, 1, fin);
dwPos = SwapLong(dwPos);
// read start of next record
fseek(fin, 0x5E + 8*i, SEEK_SET);
fread(&dwRecLen, 4, 1, fin);
dwRecLen = SwapLong(dwRecLen);
// for the last, use the file len
if (i==nRecs-1) dwRecLen = dwLen;
dwRecLen -= dwPos;
fseek(fin,dwPos,SEEK_SET);
int n = fread(t.buf, 1, dwRecLen, fin);
t.len = n;
if(bCompressed)
t.Decompress();
#ifndef UNIX
// check for CR insert
if (!bBinary)
t.DuplicateCR();
#endif
if(!bQuiet) printf("\rreconverting %s: record %d of %d",head.sN
ame,i,nRecs);
fwrite(t.buf, 1, t.Len(), fout);
}
fclose(fin);
fclose(fout);
}
//////////////////////////////////////////////////
// Encode Mode
//////////////////////////////////////////////////
void Encode(char* src, char* dest, char* title, int bQuiet, int bBinary,
int bReport, int bCompress, int bPrivate, int bCategory)
{
FILE* fin;
FILE* fout;
tDocHeader head1;
if ( bPrivate > 1)
{
bPrivate = 0;
}
if ( bCategory > 15)
{
bCategory = 0;
}
if ( dest[0] == '\0' )
{
if(strrchr(src, '/'))
{
strcpy(dest, strrchr(src, '/')+1);
}
else
{
strcpy(dest, src);
}
strcat(dest, ".pdb");
}
if ( title[0] == '\0' )
{
if(strrchr(src, '/'))
{
strcpy(title, strrchr(src, '/')+1);
}
else
{
strcpy(title, src);
}
}
unsigned long index;
if(bPrivate)
{
index = 0x50000000; // private and dirty
}
else
{
index = 0x40000000; // dirty
}
index = index + (bCategory * 0x1000000); // set category
index = index + 0x6F8000; // unique_id=0x6f8000
fin = fopen(src,"rb");
fout = fopen(dest,"wb");
if (fin==0 || fout==0)
{
printf("problem opening files");
#if UNIX
printf("\n");
#endif
exit(2);
}
fseek(fin,0,SEEK_END);
DWORD storySize = ftell(fin);
fseek(fin,0,SEEK_SET);
DWORD x;
WORD w;
long recSize = 4096;
DWORD z,numRecs;
sprintf(head1.sName,"%.31s",title);
head1.sName[31] = 0;
if(!bQuiet) printf("Saving to %s as <%s>,%s%s compressed", dest, title,
bBinary ? " binary mode," : "",
bCompress ? "" : " not");
/*LocalWrite just writes to the new file the number of bytes st
arting at the passed pointer*/
head1.dwUnknown1 = 0;
strncpy((char *)&head1.dwTime1, "\x06\xD1\x44\xAE", 4);
strncpy((char *)&head1.dwTime2, "\x06\xD1\x44\xAE", 4);
head1.dwTime3 = 0;
head1.dwLastSync = 0;
head1.ofsSort = 0;
head1.ofsCatagories = 0;
strncpy((char *)&head1.dwCreator, "TEXt", 4); // database creator
strncpy((char *)&head1.dwType, "REAd", 4); // database type
head1.dwUnknown2 = 0;
head1.dwUnknown3 = 0;
z = (int) (storySize/(long) recSize);
if (((long) z * recSize) < storySize)
z ++;
numRecs = z;
z ++;
head1.wNumRecs = SwapWord(z); // the number of records to fo
llow
fwrite(&head1,1,DOCHEADSZ,fout);
x = 0x50L + (long) z * 8;
out_long(x,fout); // start writing the record offsets
out_long(index,fout);
x += 0x0010L;
index++;
z--;
while(z--) {
out_long(x,fout); //more record offsets
out_long(index++,fout); // the attributes + ID's
x += 0x1000L;
}
// one more word.....
out_word(0,fout);
tDocRecord0 rec0;
rec0.wVersion = SwapWord(bCompress ? 2 : 1);
rec0.wSpare = 0;
rec0.dwStoryLen = SwapLong(storySize);
rec0.wNumRecs = SwapWord(SwapWord(head1.wNumRecs) - 1);
rec0.wRecSize = SwapWord(recSize);
rec0.dwSpare2 = 0;
fwrite(&rec0,1,sizeof(rec0),fout);
int n = recSize;
// dump the whole story into the new file
int recNum = 0;
if(!bQuiet) printf("\n");
tBuf buf;
while(recNum < numRecs)
{
long pos;
pos = ftell(fout);
fseek(fout, 0x56 + 8*recNum, SEEK_SET);
if (recNum!=numRecs) out_long(pos,fout);
fseek(fout, pos, SEEK_SET);
int nOrg;
buf.Clear();
nOrg = n = fread(buf.buf,1,4096,fin);
buf.len = n;
if (n==0) break;
if (!bBinary)
buf.RemoveBinary();
if (bCompress)
buf.Compress();
n = fwrite(buf.buf,1,buf.Len(),fout);
if(!bQuiet) printf("\rconverting record %d of %d",recNum+1,numR
ecs);
if (bReport && n && bCompress)
if(!bQuiet) printf("\noriginal %d bytes, compressed to
%d bytes, ratio: %f5.1\n",
nOrg, n, 100. * n / nOrg);
recNum++;
}
fclose(fin);
fclose(fout);
}
//////////////////////////////////////////////////
// Main Program
//////////////////////////////////////////////////
int
main(int argc, char** argv)
{
int iArg = 1;
int bEncode = 1;
int bDecode = 0;
int bInfo = 0;
int bModify = 0;
int bBinary = 0;
int bReport = 0;
int bCompress = 1;
int bPrivate = 2;
int bCategory = 16;
int bQuiet = 0;
char filein[250]="";
char fileout[250]="";
char title[250]="";
if ( ! SwapChoose()) {
printf("\nfailed to select proper byte swapping algorithm");
#if UNIX
printf("\n");
#endif
exit(1);
}
while (iArg < argc)
{
if (argv[iArg][0] == '-')
{
switch(argv[iArg][1])
{
case 'e' :
bEncode = 1;
bDecode = 0;
bInfo = 0;
bModify = 0;
break;
case 'd' :
bEncode = 0;
bDecode = 1;
bInfo = 0;
bModify = 0;
break;
case 'i':
bEncode = 0;
bDecode = 0;
bInfo = 1;
bModify = 0;
break;
case 'm':
bEncode = 0;
bDecode = 0;
bInfo = 0;
bModify = 1;
break;
case 'b' :
bBinary = 1;
break;
case 'r' :
bReport = 1;
break;
case 'n' :
bCompress = 0;
case 'p' :
bPrivate = 1;
if (argv[iArg][2]=='0')
bPrivate = 0;
break;
case 'c' :
char nb[3];
nb[0] = argv[iArg][2];
nb[1] = argv[iArg][3];
nb[2] = argv[iArg][4];
bCategory = atoi(nb);
break;
case 'o' :
iArg++;
strcpy(fileout, argv[iArg]);
break;
case 't' :
iArg++;
strcpy(title, argv[iArg]);
break;
case 'q' :
bQuiet = 1;
break;
}
}
else if (filein[0] == '\0')
{
strcpy(filein, argv[iArg]);
}
else if (fileout[0] == '\0')
{
strcpy(fileout, argv[iArg]);
}
else if (title[0] == '\0')
{
strcpy(title, argv[iArg]);
}
iArg++;
}
if (bInfo && filein[0] != '\0')
{
Info(filein);
}
else if (bModify && filein[0] != '\0')
{
Modify(filein, title, bQuiet, bPrivate, bCategory);
}
else if (bDecode && filein[0] != '\0')
{
Decode(filein, fileout, bQuiet, bBinary);
}
else if (bEncode && filein[0] != '\0')
{
Encode(filein, fileout, title, bQuiet, bBinary, bReport, bCompr
ess, bPrivate, bCategory);
}
else
{
printf("MakeDoc ver 0.8\n");
printf("\nmakedoc [-q] [-n] [-b] [-p#] [-c#] [-o <pdb-file>] [-t <pd
b-title>] <text-file>");
printf("\nmakedoc [-q] [-n] [-b] [-p#] [-c#] <text-file> <pdb-file>
<pdb-title>");
printf("\n encode text file to DOC format");
printf("\n");
printf("\nmakedoc -d [-q] [-b] [-o <txt-file>] <pdb-file>");
printf("\nmakedoc -d [-q] [-b] <pdb-file> <txt-file>");
printf("\n decode DOC file back to text file");
printf("\n");
printf("\nmakedoc -i <pdb-file>");
printf("\n print the DOC info (title, private flag, category)");
printf("\n");
printf("\nmakedoc -m [-q] [-p#] [-c#] [-t <pdb-title>] <pdb-file>");
printf("\n modify title, private flag, category");
printf("\n");
printf("\n -q quiet mode");
printf("\n -n builds the .pdb file without compression");
printf("\n -b option compresses/decompresses binary");
printf("\n -p private, #=0 private off (default=off)");
printf("\n -c category, #=[0-15] category number (default=0)");
printf("\n -o output filename (encoding mode default=<text-file>.p
db)");
printf("\n (decoding mode default=stdout)");
printf("\n -t title (max=31, default=<text-file>)");
#if UNIX
printf("\n");
#endif
exit(1);
}
#if UNIX
if(!bQuiet) printf("\n");
#endif
exit(0);
}